package hn.sigit.logic.queries.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.ejb.Remove;
import javax.ejb.Stateful;

import hn.sigit.logic.general.GeneralHelper;
import hn.sigit.logic.general.SpatialAnalysisHelper;
import hn.sigit.logic.queries.ParcelQueryHelper;
import hn.sigit.model.hnd.cadastre.HND_Layer;
import hn.sigit.model.hnd.cadastre.HND_Parcel;
import hn.sigit.model.ladm.spatialunit.LA_RequiredRelationshipSpatialUnit;
import hn.sigit.dao.hnd.cadastre.HND_ParcelDAO;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.AutoCreate;
import org.jboss.seam.annotations.Destroy;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;

import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.io.WKTWriter;


@Stateful
@Name(ParcelQueryHelper.NAME)
@Scope(value=ScopeType.CONVERSATION)
@AutoCreate
public class ParcelQueryHelperImpl extends QueryHelperImpl<HND_Parcel> implements Serializable, ParcelQueryHelper {
	private static final long serialVersionUID = 1L;
	
	private String searchSelector = "0";
	private String searchText;
	
	private List<HND_Parcel> selectedParcelPredecessors;
	private List<HND_Parcel> selectedParcelSuccessors;
	
	private String mapOptions;
	private String mapScript;
	
	
	@In
	private SpatialAnalysisHelper spatialAnalysisHelper;
	
	@In
	private GeneralHelper generalHelper;

	
	@Override
	public String getSearchSelector() {
		return searchSelector;
	}
	@Override
	public void setSearchSelector(String searchSelector) {
		this.searchSelector = searchSelector;
	}
	
	@Override
	public String getSearchText() {
		return searchText;
	}
	@Override
	public void setSearchText(String searchText) {
		this.searchText = searchText;
	}
	
	@Override
	public List<HND_Parcel> getQueryResultList() {
		if (queryResultList == null && searchText != null) {
			if (searchSelector.equals("0")) {
				queryResultList = HND_ParcelDAO.loadParcelsByFieldTab(Long.parseLong(searchText));
			}
			else if (searchSelector.equals("1")) {
				queryResultList = HND_ParcelDAO.loadParcelsByCadastralKey(searchText);
			}
			else if (searchSelector.equals("2")) {
				queryResultList = HND_ParcelDAO.loadParcelsByMunicipalKey(searchText);
			}
			else {
				queryResultList = HND_ParcelDAO.loadParcelsByFieldTab(Long.parseLong(searchText));
			}
		}
		//searchText = "";
		return queryResultList;
	}
	@Override
	public void setQueryResultList(List<HND_Parcel> queryResultList) {
		this.queryResultList = queryResultList;
	}
	
	@Override
	public HND_Parcel getSelected() {
		if (selected == null) {
			if (getQueryResultList() != null && getQueryResultList().size() > 0) {
				setSelected(getQueryResultList().get(0));
			}
		}
		return selected;
	}
	@Override
	public void setSelected(HND_Parcel selected) {
		if (this.selected != selected) {
			this.selected = selected;
			spatialAnalysisHelper.setSpatialZone(this.selected);
			selectedParcelPredecessors = null;
			selectedParcelSuccessors = null;
			mapOptions = null;
			mapScript = null;
		}
	}
	
	@Override
	public String doNewSearch() {
		queryResultList = null;
		setSelected(null);
		
		List<HND_Parcel> queryResult = getQueryResultList();
		if (queryResult != null && queryResult.size() > 1)
			return "/queries/parcelSearchResult.xhtml";
		
		return null;
	}
	
	@Override
	public List<HND_Parcel> getSelectedParcelPredecessors() {
		HND_Parcel hndParcel;
		if (selectedParcelPredecessors == null) {
			selectedParcelPredecessors = new ArrayList<HND_Parcel>();
			for (LA_RequiredRelationshipSpatialUnit rrsu : getSelected().getRequiredRelationshipSpatialUnits1()) {
				if (rrsu.getSpatialUnit1() instanceof HND_Parcel) {
					hndParcel = (HND_Parcel) rrsu.getSpatialUnit2();
					if (!hndParcel.isAlive())
						selectedParcelPredecessors.add(hndParcel);
				}
			}
		}
		return selectedParcelPredecessors;
	}
	@Override
	public void setSelectedParcelPredecessors(List<HND_Parcel> selectedParcelPredecessors) {
		this.selectedParcelPredecessors = selectedParcelPredecessors;
	}
	
	@Override
	public List<HND_Parcel> getSelectedParcelSuccessors() {
		HND_Parcel hndParcel;
		if (selectedParcelSuccessors == null) {
			selectedParcelSuccessors = new ArrayList<HND_Parcel>();
			for (LA_RequiredRelationshipSpatialUnit rrsu : getSelected().getRequiredRelationshipSpatialUnits2()) {
				if (rrsu.getSpatialUnit2() instanceof HND_Parcel) {
					hndParcel = (HND_Parcel) rrsu.getSpatialUnit1();
					selectedParcelSuccessors.add(hndParcel);
				}
			}
		}
		return selectedParcelSuccessors;
	}
	@Override
	public void setSelectedParcelSuccessors(List<HND_Parcel> selectedParcelSuccessors) {
		this.selectedParcelSuccessors = selectedParcelSuccessors;
	}
	
	@Override
	public String getMapOptions() {
		if (selected == null) return "";
		
		if (mapOptions == null) {
			double x1, y1, x2, y2;
			
			List<Geometry> envelopeList = new ArrayList<Geometry>();
			envelopeList.add(selected.getShape().getEnvelope());

			Set<HND_Parcel> neighbors = HND_ParcelDAO.loadNeighborsByHNDParcel(selected);
			for (HND_Parcel parcel : neighbors)
				envelopeList.add(parcel.getShape().getEnvelope());

			double[] dd = generalHelper.calcZoomEnvelope(envelopeList);
			x1 = dd[0]; y1 = dd[1]; x2 = dd[2]; y2 = dd[3];

			mapOptions = String.format("{ controls:[], " +
					"maxExtent: new OpenLayers.Bounds(%f, %f, %f, %f), " +
					"maxResolution: 26.280468750000182, " +
					"projection: new OpenLayers.Projection('%s'), " +
					"displayProjection: new OpenLayers.Projection('%s'), " +
					"units: 'm' }",
					
					x1, y1, x2, y2,
					generalHelper.getWorkingSRS(),
					generalHelper.getWorkingSRS());
		}
		
		return mapOptions;
	}

	@Override
	public String mapScript(String mapControlName) {
		if (mapScript == null) {
			WKTWriter wktWriter = new WKTWriter();
			
			StringBuffer sb = new StringBuffer(
					"var vector_style = new OpenLayers.Style({'strokeColor': '#ff0000','strokeWidth': 3});" +
					"var vector_style_map = new OpenLayers.StyleMap({'default': vector_style});" +
					"vlayer.styleMap = vector_style_map;" +
					
					"var parcel_style = new OpenLayers.Style({" +
					"	'fillColor': '#669933'," +
					"	'fillOpacity': .8," +
					"	'graphicName': 'square'," +
					"	'label': '" + (selected != null ? selected.getFieldTab() : "") + "'," +
					"	'pointRadius': 16," +
					"	'strokeColor': '#aaee77'," +
					"	'strokeDashstyle': 'solid'," +
					"	'strokeWidth': 4" +
					"});" +
					"" +
					"var selected_parcel_style = new OpenLayers.Style({" +
					"	'fillColor': '#FF0000'," +
					"	'fillOpacity': .8," +
					"	'graphicName': 'square'," +
					"	'label': '${noficha}'," +
					"	'pointRadius': 16," +
					"	'strokeColor': '#aaee77'," +
					"	'strokeDashstyle': 'solid'," +
					"	'strokeWidth': 4" +
					"});" +
					"" +
					"var parcel_style_map = new OpenLayers.StyleMap({'default': parcel_style, 'select': selected_parcel_style});" +
	
					"parcelFeaturesLayer.styleMap = parcel_style_map;" +
	
					"var parcelWKT = '" + wktWriter.write(selected.getShape()) + "';" +
					"var geom = new OpenLayers.Format.WKT().read(parcelWKT);" +
					"parcelFeaturesLayer.addFeatures(geom);"
			);
			
			for (HND_Layer layer : generalHelper.getLayerList())
				if (!layer.getFullQualifiedName().equals(generalHelper.getPrimaryWMSLayer()))
					sb.append(generalHelper.drawLayerJS(mapControlName, layer));
			
			mapScript = sb.toString();
		}
		
		return mapScript;
	}
	
	@Override
	@Destroy @Remove
	public void destroy() {}
	

}
